package com.hong.framework.redisplus.aspect;

import com.hong.framework.redisplus.RedisLockFactory;
import com.hong.framework.redisplus.RedisLockInfo;
import com.hong.framework.redisplus.RedisplusKeyGenerator;
import com.hong.framework.redisplus.annotation.RedisLock;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @author zengzh
 * @date create at 2018/5/16 15:45
 */
@Aspect
@Component
public class RedisLockAspect {

    @Autowired
    private RedisLockFactory redisLockFactory;
    @Autowired
    private RedisplusKeyGenerator redisplusKeyGenerator;

    private static final Logger LOGGER = LoggerFactory.getLogger(RedisLockAspect.class);

    @Around("@annotation(redisLock)")
    public Object around(ProceedingJoinPoint point, RedisLock redisLock) throws Throwable {
        RedisLockInfo redisLockInfo = null;
        try {
            String keyName = redisplusKeyGenerator.getKeyName(point, redisLock);
            redisLockInfo = redisLockFactory.tryLock(keyName, redisLock.expire(), redisLock.tryTimeout());
            if (null != redisLockInfo) {
                Object result = point.proceed();
                return result;
            }
        } catch (Throwable e) {
            LOGGER.error("around exception", e);
            throw e;
        } finally {
            if (null != redisLockInfo) {
                redisLockFactory.releaseLock(redisLockInfo);
            }
        }
        return null;
    }

}
